#ifndef _BLOCKBREAKER_GAME_GAMELOGIC_H__
#define _BLOCKBREAKER_GAME_GAMELOGIC_H__

#include <Comm/Include/SyncQueue.h>
#include <Comm/Include/Channel.h>
#include <TaskLib/Include/Task.h>


#include <Model/Include/Scene.h>

#include <Render/Include/Renderer.h>
#include <Render/Include/IWinWindow.h>

#include <Game/Include/Player.h>
#include <Game/Include/DistributionLogic.h>

#include <Game/Include/TimeGameEvent.h>
#include <Game/Include/CreateSceneGameEvent.h>
#include <Game/Include/InstallBlockGameEvent.h>
#include <Game/Include/InstallPlayerGameEvent.h>
#include <Game/Include/LoadFinishedGameEvent.h>
#include <Game/Include/PlayerInputGameEvent.h>

#define APP_PORT_NUMBER 1984
#define SERVER_WAIT_TIME_MS 120000
#define CLOCK_TIME_STEP_MS 50

#define BALL_VELOCITY 10.0f
#define PADDLE_VELOCITY 10.0f
#define BALL_RADIO 2.0f
#define PADDLE_WIDTH 5.0f
#define PADDLE_HEIGHT 1.0f

/// \brief class to resolve all the game logic
class GameLogic
{
public:

    typedef enum
    {
        SPACE_BAR_PRESSED,
        RIGHT_ARROW_PRESSED,
        LEFT_ARROW_PRESSED,
        SPACE_BAR_RELEASED,
        RIGHT_ARROW_RELEASED,
        LEFT_ARROW_RELEASED
    }GameInputType;

    GameLogic(IWinWindow* window);
    virtual ~GameLogic(void);

    bool init_comm();
    bool init_comm(std::string server_player1_ip);
    void load();
    void run();
    void input(const GameInputType &input_type);
    void unload();
    void finish_comm();

    void changeView();
    bool hasTheGameFinished();
    
private:
    void loadScene();
    void processEvents();
    static void main_task_function(void* user_data);
    void checkPlayerResults(Player* player);
    void addGameText();
    
    void playerHaveLostABall(Player* player);
    void installPlayerANewBall(Player* player);
    Player* getLocalPlayer();

    static void callbackChannelConected(Channel* canal, char* remote_IP, void* user_data);

    void processGameEvent(TimeGameEvent* game_event);
    void processGameEvent(CreateSceneGameEvent* game_event);
    void processGameEvent(InstallBlockGameEvent* game_event);
    void processGameEvent(InstallPlayerGameEvent* game_event);
    void processGameEvent(LoadFinishedGameEvent* game_event);
    void processGameEvent(PlayerInputGameEvent* game_event);

    /// ATRIBUTES ///
    bool is_server;
    Channel* comm_channel;
    SyncQueue* events_to_process_queue;
    DistributionLogic* distribution_logic;
    Semaphore* server_wait_for_client_connection;

    bool load_finished;

    Scene* scene;
    Player* player_one;
    Player* player_two;

    Renderer* renderer;
    IWinWindow* window;

    Task* main_task;
    // bool main_task_finished;

    bool view_in_3D;

};

#endif // _BLOCKBREAKER_GAME_GAMELOGIC_H__
